package com.ibm.cps.newmessage;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.ibm.cps.message.MessageFields;
import com.ibm.cps.message.validation.ValidatorUtil;
import com.ibm.util.JSONUtility;
import com.ibm.util.exception.CPSException;

public class MetadataInputSchema {

	public enum FieldType {
		String, Boolean, Integer, Array, Object
	}

	ArrayNode neccessarySchemaArray;
	ArrayNode optionalSchemaArray;
	Multimap<FieldType, String> type2FieldNames = HashMultimap.create();

	public MetadataInputSchema() {
		neccessarySchemaArray = JSONUtility.newArrayNode();
		optionalSchemaArray = JSONUtility.newArrayNode();
	}

	public void addField(String name, String displayName, FieldType type, boolean autoGenerateIfNotExist) {
		if (autoGenerateIfNotExist) {
			optionalSchemaArray.add(addField(name, displayName, type));
		} else {
			neccessarySchemaArray.add(addField(name, displayName, type));
		}
	}

	public ObjectNode addField(String name, String displayName, FieldType type) {
		ObjectNode node = JSONUtility.newObjectNode();
		node.put(MessageFields.NAME, name);
		node.put(MessageFields.DISPLAY_NAME, displayName);
		node.put(MessageFields.TYPE, type.name());
		type2FieldNames.put(type, name);
		return node;
	}

	public ObjectNode addField(FieldType type, String... names) {
		ObjectNode node = JSONUtility.newObjectNode();
		for (String name : names) {
			node.put(MessageFields.NAME, name);
			node.put(MessageFields.DISPLAY_NAME, name);
			node.put(MessageFields.TYPE, type.name());
			type2FieldNames.put(type, name);
		}
		return node;
	}

	public boolean validateInput(ObjectNode input) throws CPSException {
		ValidatorUtil.validateAllTypeFields(input, type2FieldNames.get(FieldType.String),
				type2FieldNames.get(FieldType.Array), type2FieldNames.get(FieldType.Boolean),
				type2FieldNames.get(FieldType.Integer), type2FieldNames.get(FieldType.Object));
		return true;
	}

}
